import {
	forwardRef,
	useEffect,
	useImperativeHandle,
	useLayoutEffect,
	useMemo,
	useRef,
	useState
} from 'react';
import { ChatContentStyle } from './style';
import { selectRecordsPage, type RecordsParam, type RecordsRes } from '../../http/chatting-records';
import { formatChatContentTime } from '../../utils/time';
import ShowMessage from './ShowMessage';
import type { GroupRes } from '../../http/chatting-group';
import type { PagePayload } from '@/utils/request';
import type { ChatContentRef } from '.';

type ChatContentProps = {
	active: GroupRes;
};
const ChatContent = forwardRef<ChatContentRef, ChatContentProps>((props, ref) => {
	const { active } = props;

	const [payload, setPayload] = useState<PagePayload<RecordsParam>>({
		pageNo: 1,
		pageSize: 20,
		param: { groupId: null }
	});
	const [historyMsg, setHistoryMsg] = useState<RecordsRes[]>([]);
	const [newMsg, setNewMsg] = useState<RecordsRes[]>([]);
	// 记录调用接口状态，防止滚动时重复调用
	const fetchFlog = useRef(false);
	// 记录最后一次滚动位置，用于判断滚动方向
	const lastScrollTop = useRef(0);
	const prevScrollHeight = useRef(0);
	const prevTimeRef = useRef<string>();
	const chatRef = useRef<HTMLDivElement>(null);
	const historyMsgRef = useRef<RecordsRes[]>([]);

	const queryRecordsList = async () => {
		const { data } = await selectRecordsPage(payload).finally(() => {
			fetchFlog.current = false;
		});
		if (data.results.length) {
			setHistoryMsg([...data.results.reverse(), ...historyMsg]);
		}
		historyMsgRef.current = data.results ?? [];
		// 记录上一次的滚动高度
		prevScrollHeight.current = chatRef.current!.scrollHeight;
	};
	useEffect(() => {
		if (payload.param?.groupId) {
			queryRecordsList();
		}
	}, [payload]);
	useEffect(() => {
		if (active) {
			setPayload((prev) => ({ ...prev, param: { groupId: active.id }, pageNo: 1 }));
		}
		return () => {
			setHistoryMsg([]);
			setNewMsg([]);
			historyMsgRef.current = [];
		};
	}, [active]);

	// 滚动条默认到最底部
	const scrollToBottom = () => {
		chatRef.current!.scrollTop = chatRef.current!.scrollHeight;
		// 记录上一次的滚动高度
		prevScrollHeight.current = chatRef.current!.scrollHeight;
	};
	useLayoutEffect(() => {
		if (historyMsg.length <= payload.pageSize) {
			scrollToBottom();
		} else {
			chatRef.current!.scrollTop = chatRef.current!.scrollHeight - prevScrollHeight.current;
		}
	}, [historyMsg]);

	useLayoutEffect(() => {
		scrollToBottom();
	}, [newMsg]);

	// 加载更多历史消息
	const loadMore = () => {
		if (
			chatRef.current.scrollTop <= 10 &&
			!fetchFlog.current &&
			chatRef.current.scrollTop < lastScrollTop.current
		) {
			fetchFlog.current = true;
			setPayload((prev) => ({
				...prev,
				pageNo: historyMsgRef.current.length ? prev.pageNo + 1 : prev.pageNo
			}));
		}
		lastScrollTop.current = chatRef.current.scrollTop;
	};
	useEffect(() => {
		if (chatRef.current) {
			chatRef.current.addEventListener('scroll', loadMore);
		}
		return () => {
			if (chatRef.current) {
				chatRef.current.removeEventListener('scroll', loadMore);
			}
		};
	}, []);

	// 历史消息不必重新渲染
	const HistoryMsg = useMemo(() => {
		if (historyMsg.length === 0) return;
		return historyMsg.map((item) => {
			const showTime = formatChatContentTime(item.createdTime) !== prevTimeRef.current;
			prevTimeRef.current = formatChatContentTime(item.createdTime);
			return (
				<ShowMessage key={item.id} showTime={showTime} showName={active.users > 2} message={item} />
			);
		});
	}, [historyMsg]);

	// 新消息
	const NewMsg = useMemo(() => {
		if (!newMsg || newMsg.length === 0) return;
		return newMsg.map((item) => {
			const showTime = formatChatContentTime(item.createdTime) !== prevTimeRef.current;
			prevTimeRef.current = formatChatContentTime(item.createdTime);

			return (
				<ShowMessage key={item.id} showTime={showTime} showName={active.users > 2} message={item} />
			);
		});
	}, [newMsg]);

	// 刷新消息
	const refreshNewMsg: ChatContentRef['refreshNewMsg'] = (data) => {
		if (data.message.groupId === active.id) {
			const newList = [...newMsg];
			newList.push(data.message);
			setNewMsg(newList);
		}
	};

	// 暴露方法
	useImperativeHandle(ref, () => ({
		refreshNewMsg,
		clearMsg: () => {
			setHistoryMsg([]);
			setNewMsg([]);
		}
	}));

	return (
		<ChatContentStyle ref={chatRef}>
			{/* 历史消息 */}
			{HistoryMsg}
			{/* 新消息 */}
			{NewMsg}
		</ChatContentStyle>
	);
});

export default ChatContent;
